package cn.wangxl.group.rpc.server;

import cn.wangxl.group.rpc.handler.RequestHandler;
import cn.wangxl.group.rpc.protocol.Protocol;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Deacription BioRpcServer
 * @Author 20112128
 * @Date 2020/9/23 11:23
 **/
public class NettyRpcServer extends RpcServer{

    private volatile boolean run;

    private RequestHandler requestHandler;

    public NettyRpcServer(RequestHandler requestHandler, int port, Protocol protocol) {
        this.requestHandler = requestHandler;
        setPort(port);
        setProtocol(protocol);
    }

    @Override
    public void start() {
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        EventLoopGroup eventLoopGroup1 = new NioEventLoopGroup();
        EventLoopGroup eventLoopGroup2 = new NioEventLoopGroup();
        serverBootstrap
                .group(eventLoopGroup1,eventLoopGroup2)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer(){
                    @Override
                    protected void initChannel(Channel ch) throws Exception {
                        ch.pipeline().addLast(new NettyServerHandler(requestHandler));
                    }
                });
        try {
            ChannelFuture channelFuture = serverBootstrap.bind(getPort()).sync();
            System.out.println("服务启动成功");
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            try {
                eventLoopGroup1.shutdownGracefully().sync();
                eventLoopGroup2.shutdownGracefully().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("BIO服务暂停");
    }

    static class ServerHandler implements Runnable{

        private Socket socket;

        private RequestHandler requestHandler;

        public ServerHandler(Socket socket,RequestHandler requestHandler) {
            this.socket = socket;
            this.requestHandler = requestHandler;
        }

        @Override
        public void run() {
            InputStream in = null;
            OutputStream out = null;
            try {
                in = socket.getInputStream();
                out = socket.getOutputStream();
                System.out.println(in.available());
                byte[] requestData = null;
                if(in.available()>0){
                    requestData = new byte[in.available()];
                    in.read(requestData);
                }
                byte[] responseData = requestHandler.handleRequest(requestData);
                out.write(responseData);
                out.flush();

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                in = null;
                out = null;
                socket = null;
            }
        }
    }

    @Override
    public void stop() {
        this.run = false;
    }
}
